Skip to main content

CGI fast-cgi php-fpm

什么是CGI?

早期的web server只可以处理简单的静态web文件,但是随着技术的发展出现动态语言如PHP,Python。PHP语言交给PHP解析器进行处理,但是处理之后如何和web server进行通信呢? 为了解决不同的语言处理器与web server之间的通讯,出现了CGI协议。只要按照CGI协议编写程序,就可以实现与语言解析器与web server之间的通讯。 CGI协议虽然解决了语言解析器和seb server之间通讯的问题,但是它的效率很低。因为web server每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候再关闭进程。对于每一个创建的CGI进程都会执行这些操作。所以效率很低。

什么是FastCGI?

FastCGI是用来提高CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程。而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了。大大提升了处理效率。

什么是PHP-FPM?

PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server的请求。worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进程PHP代码的处理。


CGI:

CGI的英文是(COMMON GATEWAY INTERFACE)公共网关接口,它的作用就是帮助服务器与语言通信,这里就是nginx和php进行通信,因为nginx和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个沟通的协议。 nginx服务器在接受到浏览器传递过来的数据后,如果请求的是静态的页面或者图片等无需动态处理的则会直接根据请求的url找到其位置然后返回给浏览器,这里无需php参与,但是如果是一个动态的页面请求,这个时候nginx就必须与php通信,这个时候就会需要用到cgi协议,将请求数据转换成php能理解的信息,然后php根据这些信息返回的信息也要通过cgi协议转换成nginx可以理解的信息,最后nginx接到这些信息再返回给浏览器。

fast-cgi:

传统的cgi协议在每次连接请求时,会开启一个进程进行处理,处理完毕会关闭该进程,因此下次连接,又要再次开启一个进程进行处理,因此有多少个连接就有多少个cgi进程,这也就是为什么传统的cgi会显得缓慢的原因,因此过多的进程会消耗资源和内存。 而fast-cgi则是一个进程可以处理多个请求,和上面的cgi协议完全不一样,cgi是一个进程只能处理一个请求,这样就会导致大量的cgi程序,因此会给服务器带来负担。

php-cgi:

php-fpm:

php-fpm是php提供给web serve也就是http前端服务器的fastcgi协议接口程序,它不会像php-cgi一样每次连接都会重新开启一个进程,处理完请求又关闭这个进程,而是允许一个进程对多个连接进行处理,而不会立即关闭这个进程,而是会接着处理下一个连接。它可以说是php-cgi的一个管理程序,是对php-cgi的改进。 php-fpm会开启多个php-cgi程序,并且php-fpm常驻内存,每次web serve服务器发送连接过来的时候,php-fpm将连接信息分配给下面其中的一个子程序php-cgi进行处理,处理完毕这个php-cgi并不会关闭,而是继续等待下一个连接,这也是fast-cgi加速的原理,但是由于php-fpm是多进程的,而一个php-cgi基本消耗7-25M内存,因此如果连接过多就会导致内存消耗过大,引发一些问题,例如nginx里的502错误。

同时php-fpm还附带一些其他的功能:

例如平滑过渡配置更改,普通的php-cgi在每次更改配置后,需要重新启动才能初始化新的配置,而php-fpm是不需要,php-fpm分将新的连接发送给新的子程序php-cgi,这个时候加载的是新的配置,而原先正在运行的php-cgi还是使用的原先的配置,等到这个连接后下一次连接的时候会使用新的配置初始化,这就是平滑过渡


在2000年或更早的时候,CGI比较盛行。那时,Perl是编写CGI的主流语言,以至于一般的CGI程序就是Perl程序。

由于CGI程序的性能极其低下且安全性较差,现在基本没人使用。越来越多的人开始使用Web服务器内置模块和FastCGI程序。例如,apache服务器的mod_php,nginx服务器对FastCGI的支持。

1. CGI

CGI(Common Gateway Interface),公共网关接口,它是Web服务器与外部应用程序(CGI程序)之间传递信息的接口标准。通过CGI接口,Web服务器就能够获取客户端提交的信息,并转交给服务器端的CGI程序处理,最后返回结果给客户端。

也就是说,CGI实际上是一个接口标准。我们通常所说的CGI是指CGI程序,即实现了CGI接口标准的程序。

只要某种语言具有标准输入、输出和环境变量,如perl、php、C等,就可以用来编写CGI程序。

CGI程序的工作方式:

Web服务器一般只处理静态文件请求(如 jpg、htm、html),如果碰到一个动态脚本请求(如php),web服务器主进程,就fork出一个新的进程来启动CGI程序,也就是说将动态脚本请求交给CGI程序来处理。启动CGI程序需要一个过程,比如,读取配置文件,加载扩展等。CGI程序启动后,就会解析动态脚本,然后将结果返回给Web服务器,最后Web服务器再将结果返回给客户端,刚才fork的进程也会随之关闭。

这样,每次用户请求动态脚本,Web服务器都要重新fork一个新进程,去启动CGI程序,由CGI程序来处理动态脚本,处理完后进程随之关闭。

这种工作方式的效率是非常低下的。

2. Web服务器内置模块

后来,出现了一种比较高效的方式:Web服务器内置模块。例如,apache的mod_php模块。将php解释器做成模块,然后加载到apache服务器中。

这样,apache服务器在启动的时候,就会同时启动php模块。当客户端请求php文件时,apache服务器就不用再fork出一个新进程来启动php解释器,而是直接将php文件交给运行中的php模块处理。显然,这种方式下,效率会比较高。

由于在apache服务器启动时,才会读取php的配置文件,加载php模块,在apache的运行过程中 ,不会再重新读取php的配置文件。所以,每次我们修改了php的配置文件后,必须重启apache,新的php配置文件才会生效。

3. FastCGI

FastCGI就像是一个常驻(long-live)型的CGI程序,它可以一直运行着。FastCGI程序也可以和Web服务器分别部署在不同的主机上,它还可以接受来自其他Web服务器的请求。

FastCGI也是语言无关的。其主要行为是将CGI解释器进程保持在内存中并因此获得高效的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因。

FastCGI是一种进程管理工具,它可以在内存中管理CGI进程。

FastCGI进程管理器需要单独启动。启动FastCGI后,会生成一个FastCGI主进程和多个子进程(子进程其实就是CGI解释器进程)。

当客户端请求Web服务器上的动态脚本时,Web服务器会将动态脚本通过TCP协议交给FastCGI主进程,FastCGI主进程根据情况,安排一个空闲的子进程来解析动态脚本,处理完成后将结果返回给Web服务器,Web服务器再将结果返回给客户端。该客户端请求处理完毕后,FastCGI子进程并不会随之关闭,而是继续等待主进程安排工作任务。

由此可知,FastCGI的工作效率是非常高的。

4. php-fpm

fpm是FastCGI Process Manager的缩写,那么,fpm就是FastCGI进程管理器的简称。

php-fpm就是php中的FastCGI进程管理器。 对于php5.3之前的版本来说,php-fpm是一个第三方的补丁包,旨在将FastCGI进程管理整合进PHP包中。

在php5.3之后的版本中,php-fpm不再是第三方的包,它已经被集成到php的源码中了。php-fpm提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,比spawn-fcgi具有更多优点,所以php-fpm被PHP官方收购了。